{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8b7114f7-abee-4b4f-a9bf-fbd7ac553357",
   "metadata": {},
   "source": [
    "**Load environmental variables**: See \"Getting setup\" in the first modele.  `dotenv` [docs](https://pypi.org/project/python-dotenv/) will look for `../.env`. If it finds it, it will load environmental variables from there, overriding any variables in the current shell. If it is not found, variables currently in the shell are used."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "38cb48f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "load_dotenv(os.path.join(\"..\", \".env\"), override=True)\n",
    "\n",
    "# automatically reload all modules before executing new code. The captures changes in local packages.\n",
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "09dd8911",
   "metadata": {
    "vscode": {
     "languageId": "plaintext"
    }
   },
   "source": [
    "## Create React Agent  - Prebuilt\n",
    "\n",
    "<img src=\"./assets/agent_header.png\" width=\"800\" style=\"display:block; margin-left:0;\">\n",
    "\n",
    "In this course, you're going to build a [Deep Agent](https://blog.langchain.com/deep-agents/). We'll build this on top of LangGraph's 'pre-built' agent abstraction, which simplifies the code significantly. In this lesson, you'll learn about the pre-built ReAct agent. Here's what you will learn:\n",
    "- What is a ReAct Agent\n",
    "- The capabilities of our implementation and where to find out more.\n",
    "    - Build an agent with tools\n",
    "    - The graph, state and messages\n",
    "    - Access and modify state with tools\n",
    "    - <span style=\"font-size:0.8em;\">🪝</span> hooks! and structured responses\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b96d31dc-3ffb-4afb-85ef-5e10f9a85f24",
   "metadata": {},
   "source": [
    "### What is a ReAct agent \n",
    "\n",
    "\n",
    "<img src=\"./assets/agent.png\"\n",
    "     style=\"float:left; max-width:300px; height:auto; margin:0 1rem 0.5rem 0;\">\n",
    "<div style=\"max-width: 1250px;\">\n",
    "    \n",
    "You will be using LangGraph's open-source `create_react_agent` ([see here](https://langchain-ai.github.io/langgraph/reference/agents/#langgraph.prebuilt.chat_agent_executor.create_react_agent)) abstraction. A **ReAct agent** is an AI agent that uses the \"Reasoning and Acting\" (ReAct) framework to combine chain-of-thought (CoT) reasoning with external tool use. It was made popular by the paper [ReAct: Synergizing Reasoning and Acting in Language Models](https://arxiv.org/abs/2210.03629). \n",
    "\n",
    "This agent consists of three components: a large language model (LLM), a set of tools it can use, and a prompt that provides instructions.\n",
    "\n",
    "The LLM operates in a loop. In each iteration, it examines its context, which includes a list of available tools; It decides if it needs to call a tool. It selects a tool to invoke, forms the tool call. This is sent to a tool node for execution. The tool node executes the tool(s), and sends the results (observations) back to the LLM. The LLM receives the observations(s) and uses that observation to inform the next action. The loop continues until a stopping condition is met — typically when the agent decides it no longer needs to call more tools.\n",
    "</div>\n",
    "\n",
    "<div style=\"clear:both;\"></div>\n",
    "\n",
    ">  Note: The `create_react_agent` is moving in the soon-to-be-released V1! It will be in LangChain and the name changed to simple `create_agent`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee33aed8-3c03-4fe3-b2ba-ae448ad86111",
   "metadata": {
    "jp-MarkdownHeadingCollapsed": true
   },
   "source": [
    "#### Build an agent with tools\n",
    "\n",
    "Let's start by creating an agent with a simple calculator tool to get started. Once you see how things are put together, we'll go over more details.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "77dbbaf1-a3d2-4094-80c6-55dbb1632f21",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Annotated, List, Literal, Union\n",
    "\n",
    "from langchain_core.messages import ToolMessage\n",
    "from langchain_core.tools import InjectedToolCallId, tool\n",
    "from langgraph.prebuilt import InjectedState\n",
    "from langgraph.types import Command\n",
    "\n",
    "\n",
    "@tool\n",
    "def calculator(\n",
    "    operation: Literal[\"add\",\"subtract\",\"multiply\",\"divide\"],\n",
    "    a: Union[int, float],\n",
    "    b: Union[int, float],\n",
    ") -> Union[int, float]:\n",
    "    \"\"\"Define a two-input calculator tool.\n",
    "\n",
    "    Arg:\n",
    "        operation (str): The operation to perform ('add', 'subtract', 'multiply', 'divide').\n",
    "        a (float or int): The first number.\n",
    "        b (float or int): The second number.\n",
    "        \n",
    "    Returns:\n",
    "        result (float or int): the result of the operation\n",
    "    Example\n",
    "        Divide: result   = a / b\n",
    "        Subtract: result = a - b\n",
    "    \"\"\"\n",
    "    if operation == 'divide' and b == 0:\n",
    "        return {\"error\": \"Division by zero is not allowed.\"}\n",
    "\n",
    "    # Perform calculation\n",
    "    if operation == 'add':\n",
    "        result = a + b\n",
    "    elif operation == 'subtract':\n",
    "        result = a - b\n",
    "    elif operation == 'multiply':\n",
    "        result = a * b\n",
    "    elif operation == 'divide':\n",
    "        result = a / b\n",
    "    else: \n",
    "        result = \"unknown operation\"\n",
    "    return result\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "95c0fc53",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "from langchain.chat_models import init_chat_model\n",
    "from langchain_core.tools import tool\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "from utils import format_messages\n",
    "\n",
    "# Create agent using create_react_agent directly\n",
    "\n",
    "SYSTEM_PROMPT = \"You are a helpful arithmetic assistant who is an expert at using a calculator.\"\n",
    "\n",
    "model = init_chat_model(model=\"openai:gpt-4.1-mini\", temperature=0.0)\n",
    "tools = [calculator]\n",
    "\n",
    "# Create agent\n",
    "agent = create_react_agent(\n",
    "    model,\n",
    "    tools,\n",
    "    prompt=SYSTEM_PROMPT,\n",
    "    #state_schema=AgentState,  # default\n",
    ").with_config({\"recursion_limit\": 20})  #recursion_limit limits the number of steps the agent will run\n",
    "\n",
    "# Show the agent\n",
    "display(Image(agent.get_graph(xray=True).draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "6e2aa0ee-0e6b-49ac-9085-39f5f50969ba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "langgraph.graph.state.CompiledStateGraph"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# create_react_agent returns a compiled graph\n",
    "type(agent)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "abf73e64-eb00-4d13-89cb-5857e4861f34",
   "metadata": {},
   "source": [
    "###  The graph, state and messages\n",
    "You'll run the agent in a moment, but let's dig into the graph a little bit. \n",
    "You can examine the code that implements `create_react_agent` [here](https://github.com/langchain-ai/langgraph/blob/c37c9cbab3287f0988fabe2b853569a23960e3db/libs/prebuilt/langgraph/prebuilt/chat_agent_executor.py) if you would like to see the details.  If you would like to try building a simple version of this yourself, you can check out [Foundation: Introduction to LangGraph, Module 1, Lesson 6, Agent](https://academy.langchain.com/courses/take/intro-to-langgraph/lessons/58239232-lesson-6-agent).\n",
    "\n",
    "**Defining the Agent**: When you define an agent as you did above, you provide: the model, one or more tools, a \"system\" prompt, and state schema which defaults to <a href=\"https://github.com/langchain-ai/langgraph/blob/e365b2b8bd695e03d758b19ff109152b2e342a87/libs/prebuilt/langgraph/prebuilt/chat_agent_executor.py#L62-L69\">\n",
    "  <code style=\"color:#0366d6;\">AgentState</code>\n",
    "</a> which is primarily a list of messages. ([Call details here.](https://langchain-ai.github.io/langgraph/reference/agents/#langgraph.prebuilt.chat_agent_executor.create_react_agent))\n",
    "Under the hood, this is defining and compiling the LangGraph graph shown above. An important detail is that the tools node is another pre-built item, a `ToolNode`, described [here](https://github.com/langchain-ai/langgraph/blob/e365b2b8bd695e03d758b19ff109152b2e342a87/libs/prebuilt/langgraph/prebuilt/tool_node.py#L239-L293). A tool node will run all the tools identified in the message from the LLM and return the results.\n",
    "\n",
    "**Invoking the Agent:** \n",
    "Let's call the agent and see what we get!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3d2648f0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #000080; text-decoration-color: #000080\">╭─────────────────────────────────────────────────── 🧑 Human ────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080\">│</span> What is 3.1 * 4.2?                                                                                              <span style=\"color: #000080; text-decoration-color: #000080\">│</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[34m╭─\u001b[0m\u001b[34m──────────────────────────────────────────────────\u001b[0m\u001b[34m 🧑 Human \u001b[0m\u001b[34m───────────────────────────────────────────────────\u001b[0m\u001b[34m─╮\u001b[0m\n",
       "\u001b[34m│\u001b[0m What is 3.1 * 4.2?                                                                                              \u001b[34m│\u001b[0m\n",
       "\u001b[34m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╭───────────────────────────────────────────────────── 📝 AI ─────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> 🔧 Tool Call: calculator                                                                                        <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    Args: {                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"operation\": \"multiply\",                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"a\": 3.1,                                                                                                     <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"b\": 4.2                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> }                                                                                                               <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    ID: call_S7UsKcWI1S1I3Fxh4M3Zj0PJ                                                                            <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[37m╭─\u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m 📝 AI \u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m─╮\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m 🔧 Tool Call: calculator                                                                                        \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    Args: {                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"operation\": \"multiply\",                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"a\": 3.1,                                                                                                     \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"b\": 4.2                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m }                                                                                                               \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    ID: call_S7UsKcWI1S1I3Fxh4M3Zj0PJ                                                                            \u001b[37m│\u001b[0m\n",
       "\u001b[37m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000\">╭──────────────────────────────────────────────── 🔧 Tool Output ─────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">│</span> 13.020000000000001                                                                                              <span style=\"color: #808000; text-decoration-color: #808000\">│</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[33m╭─\u001b[0m\u001b[33m───────────────────────────────────────────────\u001b[0m\u001b[33m 🔧 Tool Output \u001b[0m\u001b[33m────────────────────────────────────────────────\u001b[0m\u001b[33m─╮\u001b[0m\n",
       "\u001b[33m│\u001b[0m 13.020000000000001                                                                                              \u001b[33m│\u001b[0m\n",
       "\u001b[33m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╭───────────────────────────────────────────────────── 📝 AI ─────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> 3.1 multiplied by 4.2 is 13.02.                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[37m╭─\u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m 📝 AI \u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m─╮\u001b[0m\n",
       "\u001b[37m│\u001b[0m 3.1 multiplied by 4.2 is 13.02.                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Example usage\n",
    "result1 = agent.invoke(\n",
    "    {\n",
    "        \"messages\": [\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": \"What is 3.1 * 4.2?\",\n",
    "            }\n",
    "        ],\n",
    "    }\n",
    ")\n",
    "\n",
    "format_messages(result1[\"messages\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b437e65-8b4f-48ec-9ab5-b988fe6b536d",
   "metadata": {},
   "source": [
    "**Invoking the Agent:** \n",
    "A sequence diagram is a great way to look at what happens when the model is invoked.\n",
    "\n",
    "<div style=\"display:none\">\n",
    "    the mermaid code is saved here for future\n",
    "```mermaid\n",
    "sequenceDiagram\n",
    "    participant U as User\n",
    "    participant A as LLM\n",
    "    participant T as Tools\n",
    "    Note over A: System message<br/>\"You are a helpful assistant...\"\n",
    "    U->>A: Initial input,<br/>\"What is 3.1 * 4.2?\"\n",
    "    loop while tool_calls present\n",
    "        A->>T: AIMessage(id=\"call_123\", tool_calls=[...])\n",
    "        T-->>A: ToolMessage(tool_call_id=\"call_123\", content=\"xx\")\n",
    "    end\n",
    "    A->>U: Return final state\n",
    "```\n",
    "</div> \n",
    "\n",
    "<img src=\"./assets/agent_sequence_diagram.png\"\n",
    "     style=\"float:left; max-width:500px; height:auto; margin:0 1rem 0.5rem 0;\">\n",
    "<div style=\"max-width: 1100px;\">\n",
    "In our example, the user input is \"What is 3.1 * 4.2?\". This, combined with the system prompt and tool descriptions, is sent to the LLM.  \n",
    "<br/>\n",
    "<p style=\"margin-bottom:0; margin-top:5px;\">The LLM decides that the calculator tool should be called. <br/> It adds an `AIMessage` to `messages`:</p>\n",
    "<pre style=\"font-size:0.85em; margin-top:5px; margin-bottom:0;\">\n",
    "<code class=\"language-python\">AIMessage(\n",
    "    content=\"\",\n",
    "    tool_calls=[{\"id\": \"call_123\",\n",
    "                 \"name\": \"calculator\",\n",
    "                 \"args\": {\"a\": 3.1, \"b\": 4.2, \"operation\": \"multiply\"}}])</code></pre>   \n",
    "</code></pre>\n",
    "<br/>\n",
    "<p style=\"margin-bottom:0;\">The tool node receives the AIMessage and processes all the tool calls. It tracks the tool_call_ids. It responds with a ToolMessage in `messages`: </p>\n",
    "<pre style=\"font-size:0.85em; margin-top:5px; margin-bottom:10px;\">\n",
    "<code class=\"language-python\">ToolMessage(\n",
    "    content=\"13.02\",         # The result of the tool execution.\n",
    "    tool_call_id=\"call_123\")  # Matches the id from the AIMessage.tool_calls\n",
    "</code></pre>\n",
    "The LLM examines the response in `messages`, decides it is done, and forms an `AIMessage` to the user.\n",
    "\n",
    "</div>\n",
    "\n",
    "<div style=\"clear:both;\"></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "784297e4-a617-41f6-a300-9ff06598c023",
   "metadata": {},
   "source": [
    "Let's look at the [trace in LangSmith](https://smith.langchain.com/public/3d2062e3-8713-4510-a797-801abe44d1f7/r). Here are some things to notice:\n",
    "- In the metadata of the call to the LLM, you will see the 'calculator' tool description.\n",
    "- The response from the model is a tool call with the arguments\n",
    "- In the final call to the LLM, notice the matching tool_call_id's provided by the tool node."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0378644e-7630-40f7-946f-00f4e5d3a912",
   "metadata": {},
   "source": [
    "#### Try your own\n",
    "Take a moment and try this on your own. Run a query, check it in LangSmith and see if it matches your expectation. Try expanding the calculator - maybe add a square function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8fb3e30b-dec9-43a4-a340-6aee9370bf80",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Try your own \n",
    "result = agent.invoke(\n",
    "    {\n",
    "        \"messages\": [\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": \"What is ...?\",\n",
    "            }\n",
    "        ],\n",
    "    }\n",
    ")\n",
    "\n",
    "format_messages(result[\"messages\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "146bef29-b1f2-45e1-883b-5fc51f6d54df",
   "metadata": {},
   "source": [
    "### Access and modify state within tools\n",
    "#### State\n",
    "One of the nice features of LangGraph is state. The graph has a typed data structure that is available to each node for the duration of the graph and can be persisted in long-term storage. You can use this to store information to share between nodes, to debug the graph, and to reset a long-running graph to an earlier time.\n",
    "\n",
    "When you define state for a graph, you define the data types and a 'reducer' function. The reducer describes how information is added to that element. This is especially useful when a task is mapped to multiple nodes, which are executed in parallel and update state simultaneously.\n",
    "\n",
    "In this example, the default `AgentState` was used. This is defined in [langgraph.prebuilt.chat_agent_executor](https://github.com/langchain-ai/langgraph/blob/e365b2b8bd695e03d758b19ff109152b2e342a87/libs/prebuilt/langgraph/prebuilt/chat_agent_executor.py).   \n",
    "\n",
    "```python\n",
    "    class AgentState(TypedDict):\n",
    "        \"\"\"The state of the agent.\"\"\"\n",
    "        messages: Annotated[Sequence[BaseMessage], add_messages]\n",
    "        remaining_steps: NotRequired[RemainingSteps]\n",
    "```\n",
    "        \n",
    "- `messages` are a list of `BaseMessage`, defined in [langchain_core](https://github.com/langchain-ai/langchain/blob/088095b663993b1e53cf616e1ca487d1739b0d71/libs/core/langchain_core/messages/base.py), which contains the messages to and from the LLM.\n",
    "    - typing.Annotated allows you to attach arbitrary metadata to a type hint. Syntax: Annotated[Type, metadata1, metadata2, ...] \n",
    "- The `add_messages` reducer will append new messages to the end of the message list.  \n",
    "- `remaining_steps` tracks the steps in a graph. You will see this initialized as the `recursion_limit`, but is tracked by the graph and not visibile to the user.  \n",
    "Let's take a look at this quickly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "35787543-06dc-43cb-8f18-2abbf7bf3b07",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": {
       "messages": [
        {
         "data": {
          "additional_kwargs": {},
          "content": "What is 3.1 * 4.2?",
          "example": false,
          "id": "d684b250-69b3-4b5b-8796-3f5a0e0d6cb2",
          "name": null,
          "response_metadata": {},
          "type": "human"
         },
         "type": "human"
        },
        {
         "data": {
          "additional_kwargs": {
           "refusal": null,
           "tool_calls": [
            {
             "function": {
              "arguments": "{\"operation\":\"multiply\",\"a\":3.1,\"b\":4.2}",
              "name": "calculator"
             },
             "id": "call_S7UsKcWI1S1I3Fxh4M3Zj0PJ",
             "type": "function"
            }
           ]
          },
          "content": "",
          "example": false,
          "id": "run--eafa8352-8dd2-4c46-acde-0b229198c152-0",
          "invalid_tool_calls": [],
          "name": null,
          "response_metadata": {
           "finish_reason": "tool_calls",
           "id": "chatcmpl-CEdpWwTcRUv0seTzBzfnRPEI3LrNL",
           "logprobs": null,
           "model_name": "gpt-4.1-mini-2025-04-14",
           "service_tier": "default",
           "system_fingerprint": "fp_ed35aa4f5f",
           "token_usage": {
            "completion_tokens": 26,
            "completion_tokens_details": {
             "accepted_prediction_tokens": 0,
             "audio_tokens": 0,
             "reasoning_tokens": 0,
             "rejected_prediction_tokens": 0
            },
            "prompt_tokens": 175,
            "prompt_tokens_details": {
             "audio_tokens": 0,
             "cached_tokens": 0
            },
            "total_tokens": 201
           }
          },
          "tool_calls": [
           {
            "args": {
             "a": 3.1,
             "b": 4.2,
             "operation": "multiply"
            },
            "id": "call_S7UsKcWI1S1I3Fxh4M3Zj0PJ",
            "name": "calculator",
            "type": "tool_call"
           }
          ],
          "type": "ai",
          "usage_metadata": {
           "input_token_details": {
            "audio": 0,
            "cache_read": 0
           },
           "input_tokens": 175,
           "output_token_details": {
            "audio": 0,
            "reasoning": 0
           },
           "output_tokens": 26,
           "total_tokens": 201
          }
         },
         "type": "ai"
        },
        {
         "data": {
          "additional_kwargs": {},
          "artifact": null,
          "content": "13.020000000000001",
          "id": "84566fa8-99bc-445a-a30f-ac725f163cd7",
          "name": "calculator",
          "response_metadata": {},
          "status": "success",
          "tool_call_id": "call_S7UsKcWI1S1I3Fxh4M3Zj0PJ",
          "type": "tool"
         },
         "type": "tool"
        },
        {
         "data": {
          "additional_kwargs": {
           "refusal": null
          },
          "content": "3.1 multiplied by 4.2 is 13.02.",
          "example": false,
          "id": "run--30db48ed-4979-4eed-a228-b34e03487153-0",
          "invalid_tool_calls": [],
          "name": null,
          "response_metadata": {
           "finish_reason": "stop",
           "id": "chatcmpl-CEdpYXdNBD7aQvMujRlAbfmexktrA",
           "logprobs": null,
           "model_name": "gpt-4.1-mini-2025-04-14",
           "service_tier": "default",
           "system_fingerprint": "fp_ed35aa4f5f",
           "token_usage": {
            "completion_tokens": 16,
            "completion_tokens_details": {
             "accepted_prediction_tokens": 0,
             "audio_tokens": 0,
             "reasoning_tokens": 0,
             "rejected_prediction_tokens": 0
            },
            "prompt_tokens": 215,
            "prompt_tokens_details": {
             "audio_tokens": 0,
             "cached_tokens": 0
            },
            "total_tokens": 231
           }
          },
          "tool_calls": [],
          "type": "ai",
          "usage_metadata": {
           "input_token_details": {
            "audio": 0,
            "cache_read": 0
           },
           "input_tokens": 215,
           "output_token_details": {
            "audio": 0,
            "reasoning": 0
           },
           "output_tokens": 16,
           "total_tokens": 231
          }
         },
         "type": "ai"
        }
       ]
      },
      "text/plain": [
       "<IPython.core.display.JSON object>"
      ]
     },
     "execution_count": 7,
     "metadata": {
      "application/json": {
       "expanded": false,
       "root": "root"
      }
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import JSON\n",
    "from langchain_core.messages import messages_to_dict\n",
    "\n",
    "JSON({\"messages\": messages_to_dict(result1[\"messages\"])})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4720982e-16c2-4b90-84d6-94aba6a13e04",
   "metadata": {},
   "source": [
    "#### Custom State\n",
    "Let's extend our calculator to keep a list of all of the operations that have been performed. This will require adding a list to state, and a reducer function to add the state to the list. This will safely handle the case where the list or operation is empty."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "1ea8d331-3e9c-4195-99a1-fa5cf6659c11",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langgraph.prebuilt.chat_agent_executor import AgentState\n",
    "\n",
    "\n",
    "def reduce_list(left: list | None, right: list | None) -> list:\n",
    "    \"\"\"Safely combine two lists, handling cases where either or both inputs might be None.\n",
    "\n",
    "    Args:\n",
    "        left (list | None): The first list to combine, or None.\n",
    "        right (list | None): The second list to combine, or None.\n",
    "\n",
    "    Returns:\n",
    "        list: A new list containing all elements from both input lists.\n",
    "               If an input is None, it's treated as an empty list.\n",
    "    \"\"\"\n",
    "    if not left:\n",
    "        left = []\n",
    "    if not right:\n",
    "        right = []\n",
    "    return left + right\n",
    "\n",
    "class CalcState(AgentState):\n",
    "    \"\"\"Graph State.\"\"\"\n",
    "    ops: Annotated[List[str], reduce_list]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aebd4660-83b9-4a23-9108-a03cbd26877a",
   "metadata": {},
   "source": [
    "#### Accessing State \n",
    "Now, we can extend our calculator to include the update. This highlights an issue! Now state is an argument to our calculator tool. \n",
    "<img src=\"./assets/state_arg_diagram.png\" width=\"800\" style=\"display:block; margin-left:0;\">\n",
    "In the diagram, it's clear that, while the LLM is tasked with generating the tool call, it cannot form the `state` argument as it does not have that in its context!  \n",
    "The solution is to **inject the state** after the LLM.\n",
    "<img src=\"./assets/inject_state_diagram.png\" width=\"1000\" style=\"display:block; margin-left:0;\"> "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a01aea69-1704-48ff-b33d-7484e35a691b",
   "metadata": {},
   "source": [
    "<div style=\"margin:0; padding:0\">\n",
    "  <p style=\"margin:0;\">This is accomplished with the <code>InjectedState</code> annotation as shown below.</p>\n",
    "  <pre style=\"font-size:0.90em; margin:0; padding-top:0;\">\n",
    "<code class=\"language-python\">    @tool\n",
    "    def calculator_wstate(\n",
    "        operation: Literal[\"add\",\"subtract\",\"multiply\",\"divide\"],\n",
    "        a: Union[int, float],\n",
    "        b: Union[int, float],\n",
    "        <span style=\"background:#fff3a3; padding:0 2px;\">state: Annotated[CalcState, InjectedState],</span>  # ← not sent to LLM\n",
    "        <span style=\"background:#fff3a3; padding:0 2px;\">tool_call_id: Annotated[str, InjectedToolCallId],</span>  # ← not sent to LLM\n",
    "    ) -> Union[int, float]:\n",
    "</code></pre>\n",
    "<p style=\"margin:0; padding-top:4px;\">\n",
    "    This strips <code>state</code> from the description provided to the LLM, and injects it when calling the tool in <code>ToolNode</code>. the <code>tool_call_id</code> is also included. This is explained in the next section.\n",
    "  </p>\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7dcaea07-fa1b-4b1a-bd1f-c7e77a6fe451",
   "metadata": {},
   "source": [
    "#### Updating State\n",
    "You may recall that tools typically return their observations to the LLM in a `ToolMessage` that is included in `messages` field in state. To update additional members of state, we would like to extend this update.  This is done using `Command` as in the return below. \n",
    "```python\n",
    "    return Command(\n",
    "        update={\n",
    "            \"ops\": ops,\n",
    "            \"messages\": [\n",
    "                ToolMessage(f\"{result}\", tool_call_id=tool_call_id)\n",
    "            ]})\n",
    "```\n",
    "Note that to create a `ToolMessage` we needed the `tool_call_id`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b52ed717-9390-437d-991c-1df0d9a337e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def calculator_wstate(\n",
    "    operation: Literal[\"add\",\"subtract\",\"multiply\",\"divide\"],\n",
    "    a: Union[int, float],\n",
    "    b: Union[int, float],\n",
    "    state: Annotated[CalcState, InjectedState],   # not sent to LLM\n",
    "    tool_call_id: Annotated[str, InjectedToolCallId] # not sent to LLM\n",
    ") -> Union[int, float]:\n",
    "    \"\"\"Define a two-input calculator tool.\n",
    "\n",
    "    Arg:\n",
    "        operation (str): The operation to perform ('add', 'subtract', 'multiply', 'divide').\n",
    "        a (float or int): The first number.\n",
    "        b (float or int): The second number.\n",
    "        \n",
    "    Returns:\n",
    "        result (float or int): the result of the operation\n",
    "    Example\n",
    "        Divide: result   = a / b\n",
    "        Subtract: result = a - b\n",
    "    \"\"\"\n",
    "    if operation == 'divide' and b == 0:\n",
    "        return {\"error\": \"Division by zero is not allowed.\"}\n",
    "\n",
    "    # Perform calculation\n",
    "    if operation == 'add':\n",
    "        result = a + b\n",
    "    elif operation == 'subtract':\n",
    "        result = a - b\n",
    "    elif operation == 'multiply':\n",
    "        result = a * b\n",
    "    elif operation == 'divide':\n",
    "        result = a / b\n",
    "    else: \n",
    "        result = \"unknown operation\"\n",
    "    ops = [f\"({operation}, {a}, {b}),\" ]\n",
    "    return Command(\n",
    "        update={\n",
    "            \"ops\": ops,\n",
    "            \"messages\": [\n",
    "                ToolMessage(f\"{result}\", tool_call_id=tool_call_id)\n",
    "            ],\n",
    "        }\n",
    "    )\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "fe5163b6-673a-4e01-a226-34c9924f837f",
   "metadata": {},
   "outputs": [],
   "source": [
    "SYSTEM_PROMPT = \"You are a helpful arithmetic assistant who is an expert at using a calculator.\"\n",
    "\n",
    "model = init_chat_model(model=\"openai:gpt-4o-mini\", temperature=0.0)\n",
    "tools = [calculator_wstate]  # new tool\n",
    "\n",
    "# Create agent\n",
    "agent = create_react_agent(\n",
    "    model,\n",
    "    tools,\n",
    "    prompt=SYSTEM_PROMPT,\n",
    "    state_schema=CalcState,  # now defining state scheme\n",
    ").with_config({\"recursion_limit\": 20})  #recursion_limit limits the number of steps the agent will run"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f666a44a-ada6-4d64-9dfd-39dfa04533b2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #000080; text-decoration-color: #000080\">╭─────────────────────────────────────────────────── 🧑 Human ────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080\">│</span> What is 3.1 * 4.2?                                                                                              <span style=\"color: #000080; text-decoration-color: #000080\">│</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[34m╭─\u001b[0m\u001b[34m──────────────────────────────────────────────────\u001b[0m\u001b[34m 🧑 Human \u001b[0m\u001b[34m───────────────────────────────────────────────────\u001b[0m\u001b[34m─╮\u001b[0m\n",
       "\u001b[34m│\u001b[0m What is 3.1 * 4.2?                                                                                              \u001b[34m│\u001b[0m\n",
       "\u001b[34m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╭───────────────────────────────────────────────────── 📝 AI ─────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> 🔧 Tool Call: calculator_wstate                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    Args: {                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"operation\": \"multiply\",                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"a\": 3.1,                                                                                                     <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"b\": 4.2                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> }                                                                                                               <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    ID: call_yunASavKVXHP9QO1PiIsjfe1                                                                            <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[37m╭─\u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m 📝 AI \u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m─╮\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m 🔧 Tool Call: calculator_wstate                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    Args: {                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"operation\": \"multiply\",                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"a\": 3.1,                                                                                                     \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"b\": 4.2                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m }                                                                                                               \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    ID: call_yunASavKVXHP9QO1PiIsjfe1                                                                            \u001b[37m│\u001b[0m\n",
       "\u001b[37m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000\">╭──────────────────────────────────────────────── 🔧 Tool Output ─────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">│</span> 13.020000000000001                                                                                              <span style=\"color: #808000; text-decoration-color: #808000\">│</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[33m╭─\u001b[0m\u001b[33m───────────────────────────────────────────────\u001b[0m\u001b[33m 🔧 Tool Output \u001b[0m\u001b[33m────────────────────────────────────────────────\u001b[0m\u001b[33m─╮\u001b[0m\n",
       "\u001b[33m│\u001b[0m 13.020000000000001                                                                                              \u001b[33m│\u001b[0m\n",
       "\u001b[33m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╭───────────────────────────────────────────────────── 📝 AI ─────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> The result of \\( 3.1 \\times 4.2 \\) is approximately \\( 13.02 \\).                                                <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[37m╭─\u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m 📝 AI \u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m─╮\u001b[0m\n",
       "\u001b[37m│\u001b[0m The result of \\( 3.1 \\times 4.2 \\) is approximately \\( 13.02 \\).                                                \u001b[37m│\u001b[0m\n",
       "\u001b[37m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Example usage\n",
    "result2 = agent.invoke(\n",
    "    {\n",
    "        \"messages\": [\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": \"What is 3.1 * 4.2?\",\n",
    "            }\n",
    "        ],\n",
    "    }\n",
    ")\n",
    "\n",
    "format_messages(result2[\"messages\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "8a55b1e3-ccba-4899-bbd3-6ab5fb729716",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": {
       "messages": [
        [
         [
          "content",
          "What is 3.1 * 4.2?"
         ],
         [
          "additional_kwargs",
          {}
         ],
         [
          "response_metadata",
          {}
         ],
         [
          "type",
          "human"
         ],
         [
          "name",
          null
         ],
         [
          "id",
          "ce033240-80ca-4324-8542-c966826b4c5a"
         ],
         [
          "example",
          false
         ]
        ],
        [
         [
          "content",
          ""
         ],
         [
          "additional_kwargs",
          {
           "refusal": null,
           "tool_calls": [
            {
             "function": {
              "arguments": "{\"operation\":\"multiply\",\"a\":3.1,\"b\":4.2}",
              "name": "calculator_wstate"
             },
             "id": "call_yunASavKVXHP9QO1PiIsjfe1",
             "type": "function"
            }
           ]
          }
         ],
         [
          "response_metadata",
          {
           "finish_reason": "tool_calls",
           "id": "chatcmpl-CEdpdachhuspjN3nOasjBkVNOhrpW",
           "logprobs": null,
           "model_name": "gpt-4o-mini-2024-07-18",
           "service_tier": "default",
           "system_fingerprint": "fp_8bda4d3a2c",
           "token_usage": {
            "completion_tokens": 28,
            "completion_tokens_details": {
             "accepted_prediction_tokens": 0,
             "audio_tokens": 0,
             "reasoning_tokens": 0,
             "rejected_prediction_tokens": 0
            },
            "prompt_tokens": 177,
            "prompt_tokens_details": {
             "audio_tokens": 0,
             "cached_tokens": 0
            },
            "total_tokens": 205
           }
          }
         ],
         [
          "type",
          "ai"
         ],
         [
          "name",
          null
         ],
         [
          "id",
          "run--3f8449bc-08e4-4980-9ec9-0d11a7e109d1-0"
         ],
         [
          "example",
          false
         ],
         [
          "tool_calls",
          [
           {
            "args": {
             "a": 3.1,
             "b": 4.2,
             "operation": "multiply"
            },
            "id": "call_yunASavKVXHP9QO1PiIsjfe1",
            "name": "calculator_wstate",
            "type": "tool_call"
           }
          ]
         ],
         [
          "invalid_tool_calls",
          []
         ],
         [
          "usage_metadata",
          {
           "input_token_details": {
            "audio": 0,
            "cache_read": 0
           },
           "input_tokens": 177,
           "output_token_details": {
            "audio": 0,
            "reasoning": 0
           },
           "output_tokens": 28,
           "total_tokens": 205
          }
         ]
        ],
        [
         [
          "content",
          "13.020000000000001"
         ],
         [
          "additional_kwargs",
          {}
         ],
         [
          "response_metadata",
          {}
         ],
         [
          "type",
          "tool"
         ],
         [
          "name",
          "calculator_wstate"
         ],
         [
          "id",
          "a5ce5b2e-cae6-4bc3-b64e-47a365abcdd1"
         ],
         [
          "tool_call_id",
          "call_yunASavKVXHP9QO1PiIsjfe1"
         ],
         [
          "artifact",
          null
         ],
         [
          "status",
          "success"
         ]
        ],
        [
         [
          "content",
          "The result of \\( 3.1 \\times 4.2 \\) is approximately \\( 13.02 \\)."
         ],
         [
          "additional_kwargs",
          {
           "refusal": null
          }
         ],
         [
          "response_metadata",
          {
           "finish_reason": "stop",
           "id": "chatcmpl-CEdpe267ELYcZ4yw90yNEXFWL9KhR",
           "logprobs": null,
           "model_name": "gpt-4o-mini-2024-07-18",
           "service_tier": "default",
           "system_fingerprint": "fp_8bda4d3a2c",
           "token_usage": {
            "completion_tokens": 26,
            "completion_tokens_details": {
             "accepted_prediction_tokens": 0,
             "audio_tokens": 0,
             "reasoning_tokens": 0,
             "rejected_prediction_tokens": 0
            },
            "prompt_tokens": 221,
            "prompt_tokens_details": {
             "audio_tokens": 0,
             "cached_tokens": 0
            },
            "total_tokens": 247
           }
          }
         ],
         [
          "type",
          "ai"
         ],
         [
          "name",
          null
         ],
         [
          "id",
          "run--9eee204d-3fdd-48f0-bc29-e1a1389034b8-0"
         ],
         [
          "example",
          false
         ],
         [
          "tool_calls",
          []
         ],
         [
          "invalid_tool_calls",
          []
         ],
         [
          "usage_metadata",
          {
           "input_token_details": {
            "audio": 0,
            "cache_read": 0
           },
           "input_tokens": 221,
           "output_token_details": {
            "audio": 0,
            "reasoning": 0
           },
           "output_tokens": 26,
           "total_tokens": 247
          }
         ]
        ]
       ],
       "ops": [
        "(multiply, 3.1, 4.2),"
       ]
      },
      "text/plain": [
       "<IPython.core.display.JSON object>"
      ]
     },
     "execution_count": 12,
     "metadata": {
      "application/json": {
       "expanded": false,
       "root": "root"
      }
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# notice the ops field is now in the response\n",
    "JSON(result2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "578f86a4-53b4-4814-9ee5-cb8919a1c9c4",
   "metadata": {},
   "source": [
    "Let's try one more example. Notice the dual tool call in this example. The tool node will execute these in parallel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "9b15902d-064c-49fe-8266-c9cc5e895344",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #000080; text-decoration-color: #000080\">╭─────────────────────────────────────────────────── 🧑 Human ────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080\">│</span> What is 3.1 * 4.2 + 5.5 * 6.5?                                                                                  <span style=\"color: #000080; text-decoration-color: #000080\">│</span>\n",
       "<span style=\"color: #000080; text-decoration-color: #000080\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[34m╭─\u001b[0m\u001b[34m──────────────────────────────────────────────────\u001b[0m\u001b[34m 🧑 Human \u001b[0m\u001b[34m───────────────────────────────────────────────────\u001b[0m\u001b[34m─╮\u001b[0m\n",
       "\u001b[34m│\u001b[0m What is 3.1 * 4.2 + 5.5 * 6.5?                                                                                  \u001b[34m│\u001b[0m\n",
       "\u001b[34m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╭───────────────────────────────────────────────────── 📝 AI ─────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> 🔧 Tool Call: calculator_wstate                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    Args: {                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"operation\": \"multiply\",                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"a\": 3.1,                                                                                                     <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"b\": 4.2                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> }                                                                                                               <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    ID: call_wXCEbA5bZujVeRQ4BJj3vcdR                                                                            <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> 🔧 Tool Call: calculator_wstate                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    Args: {                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"operation\": \"multiply\",                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"a\": 5.5,                                                                                                     <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"b\": 6.5                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> }                                                                                                               <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    ID: call_Mfnk4UZqKqrNf5T4uI5Cz9bv                                                                            <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[37m╭─\u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m 📝 AI \u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m─╮\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m 🔧 Tool Call: calculator_wstate                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    Args: {                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"operation\": \"multiply\",                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"a\": 3.1,                                                                                                     \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"b\": 4.2                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m }                                                                                                               \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    ID: call_wXCEbA5bZujVeRQ4BJj3vcdR                                                                            \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m 🔧 Tool Call: calculator_wstate                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    Args: {                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"operation\": \"multiply\",                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"a\": 5.5,                                                                                                     \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"b\": 6.5                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m }                                                                                                               \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    ID: call_Mfnk4UZqKqrNf5T4uI5Cz9bv                                                                            \u001b[37m│\u001b[0m\n",
       "\u001b[37m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000\">╭──────────────────────────────────────────────── 🔧 Tool Output ─────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">│</span> 13.020000000000001                                                                                              <span style=\"color: #808000; text-decoration-color: #808000\">│</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[33m╭─\u001b[0m\u001b[33m───────────────────────────────────────────────\u001b[0m\u001b[33m 🔧 Tool Output \u001b[0m\u001b[33m────────────────────────────────────────────────\u001b[0m\u001b[33m─╮\u001b[0m\n",
       "\u001b[33m│\u001b[0m 13.020000000000001                                                                                              \u001b[33m│\u001b[0m\n",
       "\u001b[33m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000\">╭──────────────────────────────────────────────── 🔧 Tool Output ─────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">│</span> 35.75                                                                                                           <span style=\"color: #808000; text-decoration-color: #808000\">│</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[33m╭─\u001b[0m\u001b[33m───────────────────────────────────────────────\u001b[0m\u001b[33m 🔧 Tool Output \u001b[0m\u001b[33m────────────────────────────────────────────────\u001b[0m\u001b[33m─╮\u001b[0m\n",
       "\u001b[33m│\u001b[0m 35.75                                                                                                           \u001b[33m│\u001b[0m\n",
       "\u001b[33m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╭───────────────────────────────────────────────────── 📝 AI ─────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>                                                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> 🔧 Tool Call: calculator_wstate                                                                                 <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    Args: {                                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"operation\": \"add\",                                                                                           <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"a\": 13.020000000000001,                                                                                      <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>   \"b\": 35.75                                                                                                    <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> }                                                                                                               <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>    ID: call_x6tlPJ7B6pLajZvToTuRSUVA                                                                            <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[37m╭─\u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m 📝 AI \u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m─╮\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m                                                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m 🔧 Tool Call: calculator_wstate                                                                                 \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    Args: {                                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"operation\": \"add\",                                                                                           \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"a\": 13.020000000000001,                                                                                      \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m   \"b\": 35.75                                                                                                    \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m }                                                                                                               \u001b[37m│\u001b[0m\n",
       "\u001b[37m│\u001b[0m    ID: call_x6tlPJ7B6pLajZvToTuRSUVA                                                                            \u001b[37m│\u001b[0m\n",
       "\u001b[37m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000\">╭──────────────────────────────────────────────── 🔧 Tool Output ─────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">│</span> 48.77                                                                                                           <span style=\"color: #808000; text-decoration-color: #808000\">│</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[33m╭─\u001b[0m\u001b[33m───────────────────────────────────────────────\u001b[0m\u001b[33m 🔧 Tool Output \u001b[0m\u001b[33m────────────────────────────────────────────────\u001b[0m\u001b[33m─╮\u001b[0m\n",
       "\u001b[33m│\u001b[0m 48.77                                                                                                           \u001b[33m│\u001b[0m\n",
       "\u001b[33m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╭───────────────────────────────────────────────────── 📝 AI ─────────────────────────────────────────────────────╮</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span> The result of \\( 3.1 \\times 4.2 + 5.5 \\times 6.5 \\) is \\( 48.77 \\).                                             <span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">│</span>\n",
       "<span style=\"color: #c0c0c0; text-decoration-color: #c0c0c0\">╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "\u001b[37m╭─\u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m 📝 AI \u001b[0m\u001b[37m────────────────────────────────────────────────────\u001b[0m\u001b[37m─╮\u001b[0m\n",
       "\u001b[37m│\u001b[0m The result of \\( 3.1 \\times 4.2 + 5.5 \\times 6.5 \\) is \\( 48.77 \\).                                             \u001b[37m│\u001b[0m\n",
       "\u001b[37m╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Example usage\n",
    "result3 = agent.invoke(\n",
    "    {\n",
    "        \"messages\": [\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": \"What is 3.1 * 4.2 + 5.5 * 6.5?\",\n",
    "            }\n",
    "        ],\n",
    "    }\n",
    ")\n",
    "\n",
    "format_messages(result3[\"messages\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "eddba925-7132-4972-94d2-33e21c15ed45",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/json": {
       "messages": [
        [
         [
          "content",
          "What is 3.1 * 4.2 + 5.5 * 6.5?"
         ],
         [
          "additional_kwargs",
          {}
         ],
         [
          "response_metadata",
          {}
         ],
         [
          "type",
          "human"
         ],
         [
          "name",
          null
         ],
         [
          "id",
          "156afba7-57b6-4841-ade8-095d54991354"
         ],
         [
          "example",
          false
         ]
        ],
        [
         [
          "content",
          ""
         ],
         [
          "additional_kwargs",
          {
           "refusal": null,
           "tool_calls": [
            {
             "function": {
              "arguments": "{\"operation\": \"multiply\", \"a\": 3.1, \"b\": 4.2}",
              "name": "calculator_wstate"
             },
             "id": "call_wXCEbA5bZujVeRQ4BJj3vcdR",
             "type": "function"
            },
            {
             "function": {
              "arguments": "{\"operation\": \"multiply\", \"a\": 5.5, \"b\": 6.5}",
              "name": "calculator_wstate"
             },
             "id": "call_Mfnk4UZqKqrNf5T4uI5Cz9bv",
             "type": "function"
            }
           ]
          }
         ],
         [
          "response_metadata",
          {
           "finish_reason": "tool_calls",
           "id": "chatcmpl-CEdpgausRCWugVx0pXIl0vPJGvE69",
           "logprobs": null,
           "model_name": "gpt-4o-mini-2024-07-18",
           "service_tier": "default",
           "system_fingerprint": "fp_8bda4d3a2c",
           "token_usage": {
            "completion_tokens": 72,
            "completion_tokens_details": {
             "accepted_prediction_tokens": 0,
             "audio_tokens": 0,
             "reasoning_tokens": 0,
             "rejected_prediction_tokens": 0
            },
            "prompt_tokens": 187,
            "prompt_tokens_details": {
             "audio_tokens": 0,
             "cached_tokens": 0
            },
            "total_tokens": 259
           }
          }
         ],
         [
          "type",
          "ai"
         ],
         [
          "name",
          null
         ],
         [
          "id",
          "run--4f3c00ed-5657-4c2a-95b4-bf3de709ff07-0"
         ],
         [
          "example",
          false
         ],
         [
          "tool_calls",
          [
           {
            "args": {
             "a": 3.1,
             "b": 4.2,
             "operation": "multiply"
            },
            "id": "call_wXCEbA5bZujVeRQ4BJj3vcdR",
            "name": "calculator_wstate",
            "type": "tool_call"
           },
           {
            "args": {
             "a": 5.5,
             "b": 6.5,
             "operation": "multiply"
            },
            "id": "call_Mfnk4UZqKqrNf5T4uI5Cz9bv",
            "name": "calculator_wstate",
            "type": "tool_call"
           }
          ]
         ],
         [
          "invalid_tool_calls",
          []
         ],
         [
          "usage_metadata",
          {
           "input_token_details": {
            "audio": 0,
            "cache_read": 0
           },
           "input_tokens": 187,
           "output_token_details": {
            "audio": 0,
            "reasoning": 0
           },
           "output_tokens": 72,
           "total_tokens": 259
          }
         ]
        ],
        [
         [
          "content",
          "13.020000000000001"
         ],
         [
          "additional_kwargs",
          {}
         ],
         [
          "response_metadata",
          {}
         ],
         [
          "type",
          "tool"
         ],
         [
          "name",
          "calculator_wstate"
         ],
         [
          "id",
          "fc9bd76e-3826-4af3-a76f-0129ffaff2c9"
         ],
         [
          "tool_call_id",
          "call_wXCEbA5bZujVeRQ4BJj3vcdR"
         ],
         [
          "artifact",
          null
         ],
         [
          "status",
          "success"
         ]
        ],
        [
         [
          "content",
          "35.75"
         ],
         [
          "additional_kwargs",
          {}
         ],
         [
          "response_metadata",
          {}
         ],
         [
          "type",
          "tool"
         ],
         [
          "name",
          "calculator_wstate"
         ],
         [
          "id",
          "a27f25fb-75ee-4108-98f0-691c237938c1"
         ],
         [
          "tool_call_id",
          "call_Mfnk4UZqKqrNf5T4uI5Cz9bv"
         ],
         [
          "artifact",
          null
         ],
         [
          "status",
          "success"
         ]
        ],
        [
         [
          "content",
          ""
         ],
         [
          "additional_kwargs",
          {
           "refusal": null,
           "tool_calls": [
            {
             "function": {
              "arguments": "{\"operation\":\"add\",\"a\":13.020000000000001,\"b\":35.75}",
              "name": "calculator_wstate"
             },
             "id": "call_x6tlPJ7B6pLajZvToTuRSUVA",
             "type": "function"
            }
           ]
          }
         ],
         [
          "response_metadata",
          {
           "finish_reason": "tool_calls",
           "id": "chatcmpl-CEdphTXgSbhBpmSAYa9HYRuzl6dtP",
           "logprobs": null,
           "model_name": "gpt-4o-mini-2024-07-18",
           "service_tier": "default",
           "system_fingerprint": "fp_8bda4d3a2c",
           "token_usage": {
            "completion_tokens": 32,
            "completion_tokens_details": {
             "accepted_prediction_tokens": 0,
             "audio_tokens": 0,
             "reasoning_tokens": 0,
             "rejected_prediction_tokens": 0
            },
            "prompt_tokens": 283,
            "prompt_tokens_details": {
             "audio_tokens": 0,
             "cached_tokens": 0
            },
            "total_tokens": 315
           }
          }
         ],
         [
          "type",
          "ai"
         ],
         [
          "name",
          null
         ],
         [
          "id",
          "run--93fcfaf8-d6ba-4160-919c-ae7a6b7f20c6-0"
         ],
         [
          "example",
          false
         ],
         [
          "tool_calls",
          [
           {
            "args": {
             "a": 13.020000000000001,
             "b": 35.75,
             "operation": "add"
            },
            "id": "call_x6tlPJ7B6pLajZvToTuRSUVA",
            "name": "calculator_wstate",
            "type": "tool_call"
           }
          ]
         ],
         [
          "invalid_tool_calls",
          []
         ],
         [
          "usage_metadata",
          {
           "input_token_details": {
            "audio": 0,
            "cache_read": 0
           },
           "input_tokens": 283,
           "output_token_details": {
            "audio": 0,
            "reasoning": 0
           },
           "output_tokens": 32,
           "total_tokens": 315
          }
         ]
        ],
        [
         [
          "content",
          "48.77"
         ],
         [
          "additional_kwargs",
          {}
         ],
         [
          "response_metadata",
          {}
         ],
         [
          "type",
          "tool"
         ],
         [
          "name",
          "calculator_wstate"
         ],
         [
          "id",
          "80b7eeab-b88f-4328-8d9f-a13edb6cddf4"
         ],
         [
          "tool_call_id",
          "call_x6tlPJ7B6pLajZvToTuRSUVA"
         ],
         [
          "artifact",
          null
         ],
         [
          "status",
          "success"
         ]
        ],
        [
         [
          "content",
          "The result of \\( 3.1 \\times 4.2 + 5.5 \\times 6.5 \\) is \\( 48.77 \\)."
         ],
         [
          "additional_kwargs",
          {
           "refusal": null
          }
         ],
         [
          "response_metadata",
          {
           "finish_reason": "stop",
           "id": "chatcmpl-CEdpiY7smYDwy5FW1pMhb0Pm00FlP",
           "logprobs": null,
           "model_name": "gpt-4o-mini-2024-07-18",
           "service_tier": "default",
           "system_fingerprint": "fp_8bda4d3a2c",
           "token_usage": {
            "completion_tokens": 36,
            "completion_tokens_details": {
             "accepted_prediction_tokens": 0,
             "audio_tokens": 0,
             "reasoning_tokens": 0,
             "rejected_prediction_tokens": 0
            },
            "prompt_tokens": 327,
            "prompt_tokens_details": {
             "audio_tokens": 0,
             "cached_tokens": 0
            },
            "total_tokens": 363
           }
          }
         ],
         [
          "type",
          "ai"
         ],
         [
          "name",
          null
         ],
         [
          "id",
          "run--a2d8cdcd-c532-4202-b054-269775d43bc2-0"
         ],
         [
          "example",
          false
         ],
         [
          "tool_calls",
          []
         ],
         [
          "invalid_tool_calls",
          []
         ],
         [
          "usage_metadata",
          {
           "input_token_details": {
            "audio": 0,
            "cache_read": 0
           },
           "input_tokens": 327,
           "output_token_details": {
            "audio": 0,
            "reasoning": 0
           },
           "output_tokens": 36,
           "total_tokens": 363
          }
         ]
        ]
       ],
       "ops": [
        "(multiply, 3.1, 4.2),",
        "(multiply, 5.5, 6.5),",
        "(add, 13.020000000000001, 35.75),"
       ]
      },
      "text/plain": [
       "<IPython.core.display.JSON object>"
      ]
     },
     "execution_count": 14,
     "metadata": {
      "application/json": {
       "expanded": false,
       "root": "root"
      }
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "JSON(result3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f48168b8-54bb-4b72-a494-dccbdbf2c16a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Example usage - create your own\n",
    "result4 = agent.invoke(\n",
    "    {\n",
    "        \"messages\": [\n",
    "            {\n",
    "                \"role\": \"user\",\n",
    "                \"content\": \"Create an example of your own?\",\n",
    "            }\n",
    "        ],\n",
    "    }\n",
    ")\n",
    "\n",
    "format_messages(result4[\"messages\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d93063f-9625-4667-b9d8-407b1103d4f9",
   "metadata": {},
   "source": [
    "## <span style=\"font-size:0.8em;\">🪝</span> Hooks and structured responses"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "234cce2b-7124-4933-8c34-9b5a409b4683",
   "metadata": {},
   "source": [
    "<table>\n",
    "<tr>\n",
    "<td style=\"width:300px;\">\n",
    "  <img src=\"./assets/complex_agent.png\" style=\"max-width:100%; height:auto;\">\n",
    "</td>\n",
    "<td>\n",
    "  <code>create_react_agent</code> has many additional capabilities.  \n",
    "  The course will not be using them so we will just describe them here and save exploring them to another course. \n",
    "\n",
    "  - For reference, the `create_react_agent` call definition is [here](https://langchain-ai.github.io/langgraph/reference/agents/#:~:text=of%20the%20agent.-,create_react_agent,-%C2%B6)\n",
    "\n",
    "  - pre-hook: This inserts a node prior to the agent node. It will have access to `state`. This is often used to manage messages by summarizing or compressing. See more [here](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent-manage-message-history/#keep-the-original-message-history-unmodified:~:text=to%20the%20LLM.-,def%20pre_model_hook(state)%3A,-trimmed_messages%20%3D%20trim_messages))\n",
    "  - post-hook: This inserts a node following the LLM call, prior to the tool call. This is useful for implementing human-in-the-loop, guardrails, validation, or other post-processing\n",
    "  - response_format: This adds a node before `END`. This will call and LLM.with_structured_output and the output will be formatted to match the given schema and returned in the 'structured_response' state key.\n",
    "</td>\n",
    "</tr>\n",
    "</table> \n",
    "\n",
    " "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2c2dab8-2156-4c1f-87c6-5773f841cbe3",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f1c57dd-a9cc-4e8d-9555-9eb414fb9151",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
